﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SmokinAces
{
    public static class Util
    {
        public const float MinZ = -1000.0f;
        public const float MaxZ = 1000.0f;

		/// <summary>
		/// Creates a more complicated mesh from four corners of a rectangle
		/// </summary>
		/// <param name="corners">the vertecies in the order: top-left, bottom-left, top-right, bottom-right</param>
		/// <param name="indecies">a list of integers to be filled with the indecies of triangle list primitives</param>
		/// <param name="xwidth">width in vertecies</param>
		/// <param name="ywidth">height in vertecies</param>
		/// <returns>a list of vertecies</returns>
		public static VertexPositionColorTexture[] ComplexMesh(VertexPositionColorTexture[] corners, out int[] indecies, int xwidth, int ywidth)
		{
			VertexPositionColorTexture[,] vert = new VertexPositionColorTexture[xwidth, ywidth];

			// set each  corner
			vert[0, 0] = corners[0];				// top-left
			vert[0, ywidth-1] = corners[1];			// bottom-left
			vert[xwidth-1, 0] = corners[2];			// top-right
			vert[xwidth-1, ywidth-1] = corners[3];	// bottom-right

			// interpolate!
			//--- for top and bottom
			for(int i = 0; i < xwidth; i++)
			{
				// top
				if(i != 0)
				{
					vert[i, 0] = Interp(xwidth, i, vert[0, 0], vert[xwidth-1, 0]);
				}
				// bottom
				if(i != xwidth-1)
				{
					vert[i, ywidth-1] = Interp(xwidth, i, vert[0, ywidth-1], vert[xwidth-1, ywidth-1]);
				}
				// across the rectangle
				for(int j = 1; j < ywidth-1; j++)
				{
					vert[i, j] = Interp(ywidth, j, vert[i, 0], vert[i, ywidth-1]);
				}
			}

			// generate indecies
			List<int> ilist = new List<int>();
			VertexPositionColorTexture[] vlist = new VertexPositionColorTexture[xwidth * ywidth];
			Func<int, int, int> IndexOf = (x, y) => x + y*xwidth;

			for(int i = 0; i < xwidth; i++)
			{
				for(int j = 0; j < ywidth; j++)
				{
					if(!((i == xwidth-1)||(j == ywidth-1)))
					{
						ilist.AddRange(new int[] { IndexOf(i, j), IndexOf(i, j+1), IndexOf(i+1, j) });
						ilist.AddRange(new int[] { IndexOf(i+1, j), IndexOf(i, j+1), IndexOf(i+1, j+1) });
					}
					vlist[IndexOf(i, j)] = vert[i, j];
				}
			}
			indecies = ilist.ToArray();
			return vlist;
		}

		private static Color Interp(float x1, float x2, float x, Color c1, Color c2)
		{
			float f1 = (x2 - x)/(x2 - x1);
			float f2 = (x - x1)/(x2 - x1);
			byte r = (byte)(f1 * c1.R + f2 * c2.R);
			byte g = (byte)(f1 * c1.G + f2 * c2.G);
			byte b = (byte)(f1 * c1.B + f2 * c2.B);
			byte a = (byte)(f1 * c1.A + f2 * c2.A);
			return new Color(r, g, b, a);
		}
		private static Vector2 Interp(float x1, float x2, float x, Vector2 v1, Vector2 v2)
		{
			float f1 = (x2 - x)/(x2 - x1);
			float f2 = (x - x1)/(x2 - x1);
			float nx = f1 * v1.X + f2 * v2.X;
			float ny = f1 * v1.Y + f2 * v2.Y;
			return new Vector2(nx, ny);
		}
		private static Vector3 Interp(float x1, float x2, float x, Vector3 v1, Vector3 v2)
		{
			float f1 = (x2 - x)/(x2 - x1);
			float f2 = (x - x1)/(x2 - x1);
			float nx = f1 * v1.X + f2 * v2.X;
			float ny = f1 * v1.Y + f2 * v2.Y;
			float nz = f1 * v1.Z + f2 * v2.Z;
			return new Vector3(nx, ny, nz);
		}
		private static VertexPositionColorTexture Interp(int width, int x, VertexPositionColorTexture v1, VertexPositionColorTexture v2)
		{
			return new VertexPositionColorTexture(
				Interp(0, width-1, x, v1.Position, v2.Position),
				Interp(0, width-1, x, v1.Color, v2.Color),
				Interp(0, width-1, x, v1.TextureCoordinate, v2.TextureCoordinate));
		}
	}

    public class Texture_List
    {
        public Texture2D Texture;
        public List<Delegate> Drawing_List;
        public Texture_List(GraphicsDevice graphics, String textureFileName, Draw_Delegate draw_func)
        {
            TextureCreationParameters textparams = new TextureCreationParameters();
            
            textparams.Format = SurfaceFormat.Color;
           
           this.Texture = Texture2D.FromFile(graphics, "..\\..\\..\\content\\" + textureFileName);
           //this.Texture = texturefile;
           this.Drawing_List = new List<Delegate>();
           this.Drawing_List.Add(draw_func);
        }
    }
    //---------The update delegate
    public delegate void Update_Delegate(GameTime gameTime);
    //------Because of layers I decided to create this delegate.
    public delegate void Draw_Delegate(GameTime gameTime, GraphicsDevice device);


    public class Sort_Delegate: IComparable<Sort_Delegate>
    {
        public float order;
        public Draw_Delegate draw;
        public Sort_Delegate(float order, Draw_Delegate draw)
        {
            this.order = order;
            this.draw = draw;
        }

        #region IComparable<Sort_Delegate> Members

        public int CompareTo(Sort_Delegate other)
        {
            return this.order.CompareTo(other.order);
        }

        #endregion
    }

    //------This is a list of the various layers you could draw too.
    public enum Layers
    {
        Layer0,
        Layer1,
        Layer2,
        Layer3,
        Layer4,
        Layer5,
        Layer6,
        Layer7,
        Layer8,
        Layer9,
    }

    public enum Actions
    {
        none,
        north,
        west,
        south,
        east,
        run_north,
        run_west,
        run_south,
        run_east,
        draw_sword,
        swing_sword
    }
}
